package model;

import java.util.ArrayList;
import java.util.UUID;
import model.exception.NotEnoughResourcesException;

public class Node {
	
	/**
	 * UUID univoco del nodo
	 */
	private UUID id;
	
	/**
	 * Nome del nodo
	 */
	private String name;

	/**
	 * Le interfacce di rete possedute da questo nodo
	 */
	private ArrayList<NetworkInterface> interfaces;
	
	/**
	 * Gli eventuali nodi virtuali opsitati su questo nodo
	 */
	protected ArrayList<String> hostedNodes = new ArrayList<String>(0);
	
	/**
	 * Indica l'hoster per questo nodo, null se il nodo non e' ospitato da
	 * nessun nodo, perche' non allocato o perche' nodo fisico.
	 */
	private Node hoster;
	
	/**
	 * L'IP su cui e' in ascolto il server ssh per controllare questo nodo
	 */
	private IPAddress controlIP;
	
	/**
	 * La porta su cui e' in ascolto il server ssh per controllare questo nodo
	 */
	private int controlPort = 22;
	
	
	/**
	 * @param name
	 * @param id
	 */
	public Node(String name, UUID id)
	{
		this.id = id;
		this.name=name;
		interfaces = new ArrayList<NetworkInterface>();
	}
	
	public void addInterface(NetworkInterface netInterface) 
	{	
		netInterface.setParent(this);
		interfaces.add(netInterface);
	}
	
	public void removeInterface(NetworkInterface netInterface) {
		if (netInterface == null)
			return;
		interfaces.remove(interfaces.indexOf(netInterface));
	}	

	/**
	 * Restituisce l'interfaccia con il dato nome, o null se non esiste su
	 * questo nodo.
	 * 
	 * @param interfaceName
	 * @return {@link XenNetworkInterface}
	 */
	public NetworkInterface getInterfaceByName(String name) {
		for (NetworkInterface netInterface : interfaces) {
			if (netInterface.getName().equals(name))
				return netInterface;
		}
		return null;
	}	

	/**
	 * Verifica se a questo nodo corrisponde un determinato indirizzo MAC
	 * 
	 * @param address
	 * @return {@link Boolean}
	 */
	public boolean hasAddress(MacAddress address) {
		for (NetworkInterface netInterface : interfaces) {
			if( netInterface.getMacAddress().equals(address) )
				return true;
		}
		return false;
	}
	
	
	
	/* Metodi GIA IMPLEMENTATI in Neptune*/
	/**
	 * Aggiunge un nodo virtuale a questo nodo. Se non ci sono sufficienti
	 * risorse lancia un'eccezione.
	 * 
	 * Al nodo passato, in caso di successo nella procedura di hosting, viene
	 * impostato il campo hoster opportunamente.
	 * 
	 * @param node
	 * @throws NotEnoughResourcesException
	 */
	public void addHostedNode(Node node) throws NotEnoughResourcesException {
		if (true)//(verifyHostingCapacity(node)) 
		{
			hostedNodes.add(node.getId().toString());
			node.setHoster(this);
			
		}
//		else
//			throw new NotEnoughResourcesException("The node \"" + this.getId()
//					+ "\" has not enough resources to host virtual node \""
//					+ node.getId() + "\"");
	}

	/**
	 * Rimuove un nodo virtuale ospitato su questa macchina. Se il nodo non e'
	 * ospitato su questa macchina, non fa nulla.
	 * 
	 * @param node
	 */
	public void removeHostedNode(Node node) {
		hostedNodes.remove(node.getId());
	}
	
	
	/* Metodi GET e SET*/
	public IPAddress getControlIP(){
		return controlIP;
	}
	
	public int getControlPort(){
		return controlPort;
	}
	
	public Node getHoster() {
		return hoster;
	}

	public String getName() {
		return name;
	}

	public UUID getId() {
		return id;
	}

	public ArrayList<NetworkInterface> getInterfaces() {
		return interfaces;
	}
	
	public void setHoster(Node hoster) {
		this.hoster = hoster;
	}
	
	public void setControlIP(IPAddress controlIP) {
		this.controlIP = controlIP;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setId(UUID id) {
		this.id = id;
	}

	public void setInterfaces(ArrayList<NetworkInterface> interfaces) {
		this.interfaces = interfaces;
	}
	
	@Override
	public boolean equals(Object arg0) {
		if(arg0 == null)
			return false;
		if (arg0 instanceof Node) {
			Node value = (Node) arg0;
			if(this.id == value.getId())
				return true;
		}
		return false;
	}
	
}
